from machine import Pin
from time import sleep_us

try:
    from shared_types import X595PinAssignment
    from typing import List
except:
    pass


class X595Driver:
    def __init__(self, pin_assignment: "X595PinAssignment", chip_num: int = 1) -> None:
        self.pin_clear = Pin(pin_assignment["x595_clear"], Pin.OUT)
        self.pin_clear.value(1)
        self.pin_clock = Pin(pin_assignment["x595_clock"], Pin.OUT)
        self.pin_clock.value(0)
        self.pin_latch = Pin(pin_assignment['x595_latch'], Pin.OUT)
        self.pin_latch.value(0)
        self.pin_data = Pin(pin_assignment["x595_data"], Pin.OUT)
        self.pin_data.value(0)
        self.chip_num = chip_num
        self.clear()

    def _pin_jump_up(self, pin: Pin):
        pin.on()  # 产生跳变
        sleep_us(10)  # 睡眠（事实上不睡也可以，但还是睡一下吧）
        pin.off()  # 保持一段时间后关闭

    def write_bits_from_list(self, value: "List[int|bool]") -> None:
        """
        向595写入一个列表value

        列表元素值为True时为高电平，否则为低电平。
        """
        if len(value) != self.chip_num * 8:
            raise ValueError(f"列表长度{value}与芯片有效引脚数{self.chip_num*8}不匹配")
        for bit in reversed(value):
            self.pin_data.value(1 if bit else 0)
            self._pin_jump_up(self.pin_clock)
            self._pin_jump_up(self.pin_latch)
        return

    def write_bits_from_int(self, value: int) -> None:
        """
        向595写入一个整数

        :param value: 整数
        """
        for _ in range(self.chip_num*8):
            self.pin_data.value(value & 0x01)
            self._pin_jump_up(self.pin_clock)
            self._pin_jump_up(self.pin_latch)
            value >>= 1
        return

    def clear(self):
        """
        所有位清零
        """

        self.pin_clear.value(0)
        self._pin_jump_up(self.pin_latch)
        self.pin_clear.value(1)
